/********************************************************************************************************
 * @file    gpio.h
 *
 * @brief   This is the header file for tl751x
 *
 * @author  Driver Group
 * @date    2023
 *
 * @par     Copyright (c) 2021, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
 *
 *          Licensed under the Apache License, Version 2.0 (the "License");
 *          you may not use this file except in compliance with the License.
 *          You may obtain a copy of the License at
 *
 *              http://www.apache.org/licenses/LICENSE-2.0
 *
 *          Unless required by applicable law or agreed to in writing, software
 *          distributed under the License is distributed on an "AS IS" BASIS,
 *          WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *          See the License for the specific language governing permissions and
 *          limitations under the License.
 *
 *******************************************************************************************************/
/** @page GPIO
 *
 *  Introduction
 *  ===============
 *
 *
 *  API Reference
 *  ===============
 *  Header File: gpio.h
 */
#ifndef DRIVERS_GPIO_H_
#define DRIVERS_GPIO_H_


#include "lib/include/plic.h"
#include "lib/include/analog.h"
#include "reg_include/gpio_reg.h"

/**********************************************************************************************************************
 *                                         global constants                                                           *
 *********************************************************************************************************************/

/**********************************************************************************************************************
 *                                           global macro                                                             *
 *********************************************************************************************************************/


/**********************************************************************************************************************
 *                                         global data type                                                           *
 *********************************************************************************************************************/
/**
 *  @brief  Define GPIO group types
 */
typedef enum
{
    GPIO_GROUP_A   = 0,
    GPIO_GROUP_B   = 1,
    GPIO_GROUP_C   = 2,
    GPIO_GROUP_D   = 3,
    GPIO_GROUP_E   = 4,
    GPIO_GROUP_F   = 5,
    GPIO_GROUP_G   = 6,
    GPIO_GROUP_H   = 7,
    GPIO_GROUP_I   = 8,
    GPIO_GROUP_ANA = 9,
} gpio_group_e;

/**
 *  @brief  Define GPIO types
 */
typedef enum
{
    GPIO_GROUPA   = 0x000,
    GPIO_GROUPB   = 0x100,
    GPIO_GROUPC   = 0x200,
    GPIO_GROUPD   = 0x300,
    GPIO_GROUPE   = 0x400,
    GPIO_GROUPF   = 0x500,
    GPIO_GROUPG   = 0X600,
    GPIO_GROUPH   = 0X700,
    GPIO_GROUPI   = 0X800,

    GPIO_GPOUPANA = 0x900,
    GPIO_ALL      = 0xa00,

    GPIO_PA0    = GPIO_GROUPA | BIT(0),
    GPIO_PA1    = GPIO_GROUPA | BIT(1),
    GPIO_PA2    = GPIO_GROUPA | BIT(2),
    GPIO_PA3    = GPIO_GROUPA | BIT(3),
    GPIO_USB_DM = GPIO_PA3, // default: SSPI_SI
    GPIO_PA4    = GPIO_GROUPA | BIT(4),
    GPIO_USB_DP = GPIO_PA4, // default: SSPI_CN
    GPIO_PA5    = GPIO_GROUPA | BIT(5),
    GPIO_DM     = GPIO_PA5, // default: SSPI_CK
    GPIO_PA6    = GPIO_GROUPA | BIT(6),
    GPIO_DP     = GPIO_PA6, // default: SSPI_SO
    GPIO_PA7    = GPIO_GROUPA | BIT(7),
    GPIO_SWS    = GPIO_PA7, // only support SWS_IO(default)
    GPIOA_ALL   = GPIO_GROUPA | 0x00ff,

    GPIO_PB0  = GPIO_GROUPB | BIT(0),
    GPIO_PB1  = GPIO_GROUPB | BIT(1), // default: TCK
    GPIO_PB2  = GPIO_GROUPB | BIT(2), // default: TMS
    GPIO_PB3  = GPIO_GROUPB | BIT(3), // default: TDO
    GPIO_PB4  = GPIO_GROUPB | BIT(4), // default: TDI
    GPIO_PB5  = GPIO_GROUPB | BIT(5),
    GPIO_PB6  = GPIO_GROUPB | BIT(6),
    GPIO_PB7  = GPIO_GROUPB | BIT(7),
    GPIOB_ALL = GPIO_GROUPB | 0x00ff,

    GPIO_PC0  = GPIO_GROUPC | BIT(0),
    GPIO_PC1  = GPIO_GROUPC | BIT(1),
    GPIO_PC2  = GPIO_GROUPC | BIT(2),
    GPIO_PC3  = GPIO_GROUPC | BIT(3),
    GPIO_PC4  = GPIO_GROUPC | BIT(4),
    GPIO_PC5  = GPIO_GROUPC | BIT(5),
    GPIO_PC6  = GPIO_GROUPC | BIT(6),
    GPIO_PC7  = GPIO_GROUPC | BIT(7),
    GPIOC_ALL = GPIO_GROUPC | 0x00ff,

    GPIO_PD0  = GPIO_GROUPD | BIT(0),
    GPIO_PD1  = GPIO_GROUPD | BIT(1),
    GPIO_PD2  = GPIO_GROUPD | BIT(2),
    GPIO_PD3  = GPIO_GROUPD | BIT(3),
    GPIO_PD4  = GPIO_GROUPD | BIT(4),
    GPIO_PD5  = GPIO_GROUPD | BIT(5),
    GPIO_PD6  = GPIO_GROUPD | BIT(6),
    GPIO_PD7  = GPIO_GROUPD | BIT(7),
    GPIOD_ALL = GPIO_GROUPD | 0x00ff,

    GPIO_PE0  = GPIO_GROUPE | BIT(0),
    GPIO_PE1  = GPIO_GROUPE | BIT(1),
    GPIO_PE2  = GPIO_GROUPE | BIT(2),
    GPIO_PE3  = GPIO_GROUPE | BIT(3),
    GPIO_PE4  = GPIO_GROUPE | BIT(4),
    GPIO_PE5  = GPIO_GROUPE | BIT(5),
    GPIO_PE6  = GPIO_GROUPE | BIT(6),
    GPIO_PE7  = GPIO_GROUPE | BIT(7),
    GPIOE_ALL = GPIO_GROUPE | 0x00ff,

    GPIO_PF0  = GPIO_GROUPF | BIT(0), // Only the USB1_DM_IO and gpio functions are supported
    GPIO_PF1  = GPIO_GROUPF | BIT(1), // Only the USB1_DP_IO and gpio functions are supported
    GPIO_PF2  = GPIO_GROUPF | BIT(2), // Only the DM_IO and gpio functions are supported
    GPIO_PF3  = GPIO_GROUPF | BIT(3), // Only the DP_IO and gpio functions are supported
    GPIO_PF4  = GPIO_GROUPF | BIT(4),
    GPIO_PF5  = GPIO_GROUPF | BIT(5),
    GPIO_PF6  = GPIO_GROUPF | BIT(6),
    GPIO_PF7  = GPIO_GROUPF | BIT(7),
    GPIOF_ALL = GPIO_GROUPF | 0x00ff,

    GPIO_PG0  = GPIO_GROUPG | BIT(0),
    GPIO_PG1  = GPIO_GROUPG | BIT(1),
    GPIO_PG2  = GPIO_GROUPG | BIT(2),
    GPIO_PG3  = GPIO_GROUPG | BIT(3),
    GPIO_PG4  = GPIO_GROUPG | BIT(4),
    GPIO_PG5  = GPIO_GROUPG | BIT(5),
    GPIO_PG6  = GPIO_GROUPG | BIT(6),
    GPIOG_ALL = GPIO_GROUPG | 0x00ff,

    GPIO_PH0  = GPIO_GROUPH | BIT(0),      // Only the MSPI_MOSI_IO and gpio functions are supported
    GPIO_PH1  = GPIO_GROUPH | BIT(1),      // Only the MSPI_CK_IO and gpio functions are supported
    GPIO_PH2  = GPIO_GROUPH | BIT(2),      // Only the MSPI_IO3_IO and gpio functions are supported
    GPIO_PH3  = GPIO_GROUPH | BIT(3),      // Only the MSPI_CN_IO and gpio functions are supported
    GPIO_PH4  = GPIO_GROUPH | BIT(4),      // Only the MSPI_MISO_IO and gpio functions are supported
    GPIO_PH5  = GPIO_GROUPH | BIT(5),      // Only the MSPI_IO2_IO and gpio functions are supported
    GPIO_PH6  = GPIO_GROUPH | BIT(6),      // Only the MSPI_IO4_IO and gpio functions are supported
    GPIO_PH7  = GPIO_GROUPH | BIT(7),      // Only the MSPI_IO5_IO and gpio functions are supported
    GPIOH_ALL = GPIO_GROUPH | 0x00ff,

    GPIO_PI0  = GPIO_GROUPI | BIT(0),      // Only the MSPI_IO6_IO and gpio functions are supported
    GPIO_PI1  = GPIO_GROUPI | BIT(1),      // Only the MSPI_IO7_IO and gpio functions are supported
    GPIO_PI2  = GPIO_GROUPI | BIT(2),      // default: MSPI_CN1
    GPIO_PI3  = GPIO_GROUPI | BIT(3),      // default: MSPI_CN2
    GPIO_PI4  = GPIO_GROUPI | BIT(4),      // default: MSPI_CN3
    GPIO_PI5  = GPIO_GROUPI | BIT(5),      // MSPI_DM_IO(0)
    GPIOI_ALL = GPIO_GROUPI | 0x00ff,

    GPIO_ANA0    = GPIO_GPOUPANA | BIT(0), // GPIO(default) no other functions
    GPIO_ANA1    = GPIO_GPOUPANA | BIT(1), // GPIO(default) no other functions
    GPIO_ANA_ALL = GPIO_GPOUPANA | 0x0003,
} gpio_pin_e;

/**
 *  @brief  Define GPIO function pin types.
 */
typedef enum
{
    GPIO_FC_PA0 = GPIO_PA0,
    GPIO_FC_PA1 = GPIO_PA1,
    GPIO_FC_PA2 = GPIO_PA2,
    GPIO_FC_PA3 = GPIO_PA3,
    GPIO_FC_PA4 = GPIO_PA4,
    GPIO_FC_PA5 = GPIO_PA5,
    GPIO_FC_PA6 = GPIO_PA6,

    GPIO_FC_PB0 = GPIO_PB0,
    GPIO_FC_PB1 = GPIO_PB1,
    GPIO_FC_PB2 = GPIO_PB2,
    GPIO_FC_PB3 = GPIO_PB3,
    GPIO_FC_PB4 = GPIO_PB4,
    GPIO_FC_PB5 = GPIO_PB5,
    GPIO_FC_PB6 = GPIO_PB6,
    GPIO_FC_PB7 = GPIO_PB7,

    GPIO_FC_PC0 = GPIO_PC0,
    GPIO_FC_PC1 = GPIO_PC1,
    GPIO_FC_PC2 = GPIO_PC2,
    GPIO_FC_PC3 = GPIO_PC3,
    GPIO_FC_PC4 = GPIO_PC4,
    GPIO_FC_PC5 = GPIO_PC5,
    GPIO_FC_PC6 = GPIO_PC6,
    GPIO_FC_PC7 = GPIO_PC7,

    GPIO_FC_PD0 = GPIO_PD0,
    GPIO_FC_PD1 = GPIO_PD1,
    GPIO_FC_PD2 = GPIO_PD2,
    GPIO_FC_PD3 = GPIO_PD3,
    GPIO_FC_PD4 = GPIO_PD4,
    GPIO_FC_PD5 = GPIO_PD5,
    GPIO_FC_PD6 = GPIO_PD6,
    GPIO_FC_PD7 = GPIO_PD7,

    GPIO_FC_PE0 = GPIO_PE0,
    GPIO_FC_PE1 = GPIO_PE1,
    GPIO_FC_PE2 = GPIO_PE2,
    GPIO_FC_PE3 = GPIO_PE3,
    GPIO_FC_PE4 = GPIO_PE4,
    GPIO_FC_PE5 = GPIO_PE5,
    GPIO_FC_PE6 = GPIO_PE6,
    GPIO_FC_PE7 = GPIO_PE7,


    GPIO_FC_PF4 = GPIO_PF4,
    GPIO_FC_PF5 = GPIO_PF5,
    GPIO_FC_PF6 = GPIO_PF6,
    GPIO_FC_PF7 = GPIO_PF7,

    GPIO_FC_PG0 = GPIO_PG0,
    GPIO_FC_PG1 = GPIO_PG1,
    GPIO_FC_PG2 = GPIO_PG2,
    GPIO_FC_PG3 = GPIO_PG3,
    GPIO_FC_PG4 = GPIO_PG4,
    GPIO_FC_PG5 = GPIO_PG5,
    GPIO_FC_PG6 = GPIO_PG6,


    GPIO_FC_PI2 = GPIO_PI2,
    GPIO_FC_PI3 = GPIO_PI3,
    GPIO_FC_PI4 = GPIO_PI4,
    GPIO_FC_PI5 = GPIO_PI5,


    GPIO_NONE_PIN = 0x000,
} gpio_func_pin_e;

/**
 *  @brief  select pin as DSP_JTAG
 */
typedef struct
{
    gpio_pin_e tck;
    gpio_pin_e tms;
    gpio_pin_e tdo;
    gpio_pin_e tdi;
} dsp_jtag_pin_st;

/**
 *  @brief  Define GPIO function mux types
 */
typedef enum
{
    SWM_IO         = 1,
    PWM0           = 2,
    PWM1           = 3,
    PWM2           = 4,
    PWM3           = 5,
    PWM4           = 6,
    PWM5           = 7,
    PWM0_N         = 8,
    PWM1_N         = 9,
    PWM2_N         = 10,
    PWM3_N         = 11,
    PWM4_N         = 12,
    PWM5_N         = 13,
    UART0_RTS      = 14,
    UART0_CTS_I    = 15,
    UART0_RTX_IO   = 16,
    UART0_TX       = 17,
    UART1_RTS      = 18,
    UART1_CTS_I    = 19,
    UART1_RTX_IO   = 20,
    UART1_TX       = 21,
    UART2_RTS      = 22,
    UART2_CTS_I    = 23,
    UART2_RTX_IO   = 24,
    UART2_TX       = 25,
    UART3_RTS      = 26,
    UART3_CTS_I    = 27,
    UART3_RTX_IO   = 28,
    UART3_TX       = 29,
    SPDIF_RX       = 30,
    SPDIF_TX       = 31,
    SSPI_SI_IO     = 32,
    SSPI_SO_IO     = 33,
    SSPI_CN_I      = 34,
    SSPI_CK_I      = 35,
    DSP_TDI_I      = 36,
    DSP_TDO_IO     = 37,
    DSP_TMS_I      = 38,
    DSP_TCK_I      = 39,
    CLK_7816       = 40,
    I2S0_DAT1_IO   = 41,
    I2S0_LR1_IO    = 42,
    I2S0_DAT0_IO   = 43,
    I2S0_LR0_IO    = 44,
    I2S0_BCK_IO    = 45,
    I2S0_CLK       = 46,
    I2S1_DAT1_IO   = 47,
    I2S1_LR1_IO    = 48,
    I2S1_DAT0_IO   = 49,
    I2S1_LR0_IO    = 50,
    I2S1_BCK_IO    = 51,
    I2S1_CLK       = 52,
    I2S2_DAT1_IO   = 53,
    I2S2_LR1_IO    = 54,
    I2S2_DAT0_IO   = 55,
    I2S2_LR0_IO    = 56,
    I2S2_BCK_IO    = 57,
    I2S2_CLK       = 58,
    DMIC0_DAT_I    = 59,
    DMIC0_CLK1     = 60,
    DMIC0_CLK0     = 61,
    DMIC1_DAT_I    = 62,
    DMIC1_CLK1     = 63,
    DMIC1_CLK0     = 64,
    DMIC2_DAT_I    = 65,
    DMIC2_CLK1     = 66,
    DMIC2_CLK0     = 67,
    WIFI_DENY_I    = 68,
    BT_ACTIVITY    = 69,
    BT_STATUS      = 70,
    BT_INBAND      = 71,
    TX_CYC2PA      = 72,
    ATSEL_0        = 73,
    ATSEL_1        = 74,
    ATSEL_2        = 75,
    ATSEL_3        = 76,
    RX_CYC2LNA     = 77,
    I2C_SDA_IO     = 78,
    I2C_SCL_IO     = 79,
    I2C1_SDA_IO    = 80,
    I2C1_SCL_IO    = 81,
    DBG_PROBE_CLK  = 82,
    DBG_BB0        = 83,
    DBG_ADC_I_DAT0 = 84,
    DBG_TX_DAT0_I  = 85,
    DBG_OTP_PCLK   = 86,
    DBG_OTP_DR10   = 87,
    DBG_OTP_DW10   = 88,
    EMMC_RSTN      = 89,
    EMMC_DS_I      = 90,
    EMMC_CDN_I     = 91,
    EMMC_WP_I      = 92,
    EMMC_DAT7_IO   = 93,
    EMMC_DAT6_IO   = 94,
    EMMC_DAT5_IO   = 95,
    EMMC_DAT4_IO   = 96,
    EMMC_DAT3_IO   = 97,
    EMMC_DAT2_IO   = 98,
    EMMC_DAT1_IO   = 99,
    EMMC_DAT0_IO   = 100,
    EMMC_CMD_IO    = 101,
    EMMC_CK_IO     = 102,
    GSPI_CSN3_IO   = 103,
    GSPI_CSN2_IO   = 104,
    GSPI_CSN1_IO   = 105,
    GSPI_DM_IO     = 106,
    GSPI_CSN0_IO   = 107,
    GSPI_IO7_IO    = 108,
    GSPI_IO6_IO    = 109,
    GSPI_IO5_IO    = 110,
    GSPI_IO4_IO    = 111,
    GSPI_IO3_IO    = 112,
    GSPI_IO2_IO    = 113,
    GSPI_MISO_IO   = 114,
    GSPI_MOSI_IO   = 115,
    GSPI_CLK_IO    = 116,
    LSPI_DM_IO     = 117,
    LSPI_CN_IO     = 118,
    LSPI_IO7_IO    = 119,
    LSPI_IO6_IO    = 120,
    LSPI_IO5_IO    = 121,
    LSPI_IO4_IO    = 122,
    LSPI_IO3_IO    = 123,
    LSPI_IO2_IO    = 124,
    LSPI_MISO_IO   = 125,
    LSPI_MOSI_IO   = 126,
    LSPI_CK_IO     = 127,
} gpio_func_e;

/**
 *  @brief  Define GPIO mux func
 */
typedef enum
{
    AS_GPIO,
    AS_SSPI_SI,
    AS_SSPI_CN,
    AS_SSPI_CK,
    AS_SSPI_SO,
    AS_SWS,
    AS_TCK,
    AS_TMS,
    AS_TDO,
    AS_TDI,
    AS_MSPI_MOSI,
    AS_MSPI_CK,
    AS_MSPI_IO3,
    AS_MSPI_CN,
    AS_MSPI_MISO,
    AS_MSPI_IO2,
    AS_MSPI_IO4,
    AS_MSPI_IO5,
    AS_MSPI_IO6,
    AS_MSPI_IO7,
    AS_MSPI_CN1,
    AS_MSPI_CN2,
    AS_MSPI_CN3,
    AS_MSPI_DM,
} gpio_fuc_e;

/*                                         global data type                                                           *
 *********************************************************************************************************************/

/*
 * @brief define gpio irq
 */
typedef enum
{
    GPIO_IRQ_IRQ0 = BIT(0),
    GPIO_IRQ_IRQ1 = BIT(1),
    GPIO_IRQ_IRQ2 = BIT(2),
    GPIO_IRQ_IRQ3 = BIT(3),
    GPIO_IRQ_IRQ4 = BIT(4),
    GPIO_IRQ_IRQ5 = BIT(5),
    GPIO_IRQ_IRQ6 = BIT(6),
    GPIO_IRQ_IRQ7 = BIT(7),
} gpio_irq_e;

/**
 *  @brief  Define rising/falling types
 */
typedef enum
{
    POL_RISING  = 0,
    POL_FALLING = 1,
} gpio_pol_e;

/**
 *  @brief  Define interrupt types
 */
typedef enum
{
    INTR_RISING_EDGE = 0,
    INTR_FALLING_EDGE,
    INTR_HIGH_LEVEL,
    INTR_LOW_LEVEL,
} gpio_irq_trigger_type_e;

/**
 *  @brief  Define IRQ types
 */
typedef enum
{
    GPIO_IRQ0 = 0,
    GPIO_IRQ1 = 1,
    GPIO_IRQ2 = 2,
    GPIO_IRQ3 = 3,
    GPIO_IRQ4 = 4,
    GPIO_IRQ5 = 5,
    GPIO_IRQ6 = 6,
    GPIO_IRQ7 = 7,
} gpio_irq_num_e;

/**
 *  @brief  Define pull up or down types
 */
typedef enum
{
    GPIO_PIN_UP_DOWN_FLOAT = 0,
    GPIO_PIN_PULLUP_1M     = 1,
    GPIO_PIN_PULLDOWN_100K = 2,
    GPIO_PIN_PULLUP_10K    = 3,
} gpio_pull_type_e;

/**
 *  @brief  Define pem task signal types
 */
typedef enum
{
    TASK_SIGNAL_SEL0 = 0,
    TASK_SIGNAL_SEL1 = 1,
    TASK_SIGNAL_SEL2 = 2,
    TASK_SIGNAL_SEL3 = 3,
    TASK_SIGNAL_SEL4 = 4,
    TASK_SIGNAL_SEL5 = 5,
    TASK_SIGNAL_SEL6 = 6,
    TASK_SIGNAL_SEL7 = 7,
} pem_task_signal_type_e;

/**
 *  @brief  Define pem gpio group task types, choose which gpio group  as task
 */
typedef enum
{
    TASK_GROUP_GPIO_PA = 0,
    TASK_GROUP_GPIO_PB = 1,
    TASK_GROUP_GPIO_PC = 2,
    TASK_GROUP_GPIO_PD = 3,
    TASK_GROUP_GPIO_PE = 4,
    TASK_GROUP_GPIO_PF = 5,
} pem_gpio_group_task_type_e;

typedef enum
{
    PROBE_CLK32K        = 0,
    PROBE_RC24M         = 1,
    PROBE_PLL0          = 2,
    PROBE_PLL1          = 3,
    PROBE_XTL48M        = 4,
    PROBE_HCLK          = 5,
    PROBE_PCLK          = 6,
    PROBE_CLK_CCLK_DSP  = 7,
    PROBE_CLK_MSPI      = 8,
    PROBE_CLK_NPE       = 9,
    PROBE_CLK_HCLK1_N22 = 10,
    PROBE_CLK_LSPI      = 11,
    PROBE_CLK_GSPI      = 12,
    PROBE_CLK_SDIO      = 13,
    PROBE_CLK_STIMER    = 14,
    PROBE_CLK_USBPHY    = 15,
    PROBE_CLK_USBPHY1   = 16,
    PROBE_CLK_7816      = 17,
    PROBE_CLK_ZB_MST    = 18,
    PROBE_DBG_CLK       = 19,
    PROBE_CLK_ACLK_DBG  = 20,
    PROBE_CLK_WT        = 21,
    PROBE_CLK_XO_EXT    = 22,
} probe_clk_sel_e;

/**********************************************************************************************************************
 *                                     global variable declaration                                                    *
 *********************************************************************************************************************/

/**********************************************************************************************************************
 *                                      global function prototype                                                     *
 *********************************************************************************************************************/

/**
 * @brief      This function servers to enable gpio function.
 * @param[in]  pin - the selected pin.
 * @return     none.
 */
static inline void gpio_function_en(gpio_pin_e pin)
{
    unsigned char bit = pin & 0xff;
    BM_SET(reg_gpio_func(pin), bit);
}

/**
 * @brief      This function servers to disable gpio function.
 * @param[in]  pin - the selected pin.
 * @return     none.
 */
static inline void gpio_function_dis(gpio_pin_e pin)
{
    unsigned char bit = pin & 0xff;
    BM_CLR(reg_gpio_func(pin), bit);
}

/**
 * @brief     This function set the pin's output high level.
 * @param[in] pin - the pin needs to set its output level.
 * @return    none.
 */
static inline void gpio_set_high_level(gpio_pin_e pin)
{
    unsigned char bit = pin & 0xff;
    if (((pin >> 8) & 0xff) == GPIO_GROUP_ANA) {
        analog_write_reg8(areg_gpio_pana_out_set, (analog_read_reg8(areg_gpio_pana_out_set)) | bit);
    } else {
        reg_gpio_out_set(pin) = bit;
    }
}

/**
 * @brief     This function set the pin's output low level.
 * @param[in] pin - the pin needs to set its output level.
 * @return    none.
 */
static inline void gpio_set_low_level(gpio_pin_e pin)
{
    unsigned char bit = pin & 0xff;
    if (((pin >> 8) & 0xff) == GPIO_GROUP_ANA) {
        analog_write_reg8(areg_gpio_pana_out_clear, (analog_read_reg8(areg_gpio_pana_out_clear)) | bit);
    } else {
        reg_gpio_out_clear(pin) = bit;
    }
}

/**
 * @brief     This function set the pin's output level.
 * @param[in] pin - the pin needs to set its output level
 * @param[in] value - value of the output level(1: high 0: low)
 * @return    none
 */
static inline void gpio_set_level(gpio_pin_e pin, unsigned char value)
{
    if (value) {
        gpio_set_high_level(pin);
    } else {
        gpio_set_low_level(pin);
    }
}

/**
 * @brief     This function read the pin's input level.
 * @param[in] pin - the pin needs to read its input level.
 * @return    1: the pin's input level is high.
 *            0: the pin's input level is low.
 */
static inline _Bool gpio_get_level(gpio_pin_e pin)
{
    return BM_IS_SET(reg_gpio_in(pin), pin & 0xff);
}

/**
 * @brief      This function read all the pins' input level.
 * @param[out] p - the buffer used to store all the pins' input level
 * @return     none
 */
static inline void gpio_get_level_all(unsigned char *p)
{
    p[0]  = reg_gpio_pa_in;
    p[1]  = reg_gpio_pb_in;
    p[2]  = reg_gpio_pc_in;
    p[3]  = reg_gpio_pd_in;
    p[4]  = reg_gpio_pe_in;
    p[5]  = reg_gpio_pf_in;
    p[6]  = reg_gpio_pg_in;
    p[7]  = reg_gpio_ph_in;
    p[8]  = reg_gpio_pi_in;
    p[9] = reg_gpio_pana_in;
}

/**
 * @brief     This function set the pin toggle.
 * @param[in] pin - the pin needs to toggle.
 * @return    none.
 */
static inline void gpio_toggle(gpio_pin_e pin)
{
    unsigned char bit = pin & 0xff;
    if (((pin >> 8) & 0xff) == GPIO_GROUP_ANA) {
        analog_write_reg8(areg_gpio_pana_out_toggle, (analog_read_reg8(areg_gpio_pana_out_toggle)) | bit);
    } else {
        reg_gpio_out_toggle(pin) = bit;
    }
}

/**
 * @brief      This function enable the output function of a pin.
 * @param[in]  pin - the pin needs to set the output function.
 * @return     none.
 */
static inline void gpio_output_en(gpio_pin_e pin)
{
    unsigned char bit = pin & 0xff;
    if (((pin >> 8) & 0xff) == GPIO_GROUP_ANA) {
        analog_write_reg8(areg_gpio_pana_setting, (analog_read_reg8(areg_gpio_pana_setting)) & (~(bit << 2)));
    } else {
        BM_CLR(reg_gpio_oen(pin), bit);
    }
}

/**
 * @brief      This function disable the output function of a pin.
 * @param[in]  pin - the pin needs to set the output function.
 * @return     none.
 */
static inline void gpio_output_dis(gpio_pin_e pin)
{
    unsigned char bit = pin & 0xff;
    if (((pin >> 8) & 0xff) == GPIO_GROUP_ANA) {
        analog_write_reg8(areg_gpio_pana_setting, (analog_read_reg8(areg_gpio_pana_setting)) | (bit << 2));
    } else {
        BM_SET(reg_gpio_oen(pin), bit);
    }
}

/**
 * @brief      This function enable set output function of a pin.
 * @param[in]  pin - the pin needs to set the output function (1: enable,0: disable)
 * @return     none
 */
static inline void gpio_set_output(gpio_pin_e pin, unsigned char value)
{
    if (value) {
        gpio_output_en(pin);
    } else {
        gpio_output_dis(pin);
    }
}

/**
 * @brief      This function determines whether the output function of a pin is enabled.
 * @param[in]  pin - the pin needs to determine whether its output function is enabled.
 * @return     1: the pin's output function is enabled.
 *             0: the pin's output function is disabled.
 */
static inline _Bool gpio_is_output_en(gpio_pin_e pin)
{
    unsigned char bit = pin & 0xff;
    if (((pin >> 8) & 0xff) == GPIO_GROUP_ANA) {
        return !BM_IS_SET(analog_read_reg8(areg_gpio_pana_setting), (bit << 2));
    } else {
        return !BM_IS_SET(reg_gpio_oen(pin), bit);
    }
}

/**
 * @brief     This function determines whether the input function of a pin is enabled.
 * @param[in] pin - the pin needs to determine whether its input function is enabled(not include group_pc).
 * @return    1: the pin's input function is enabled.
 *            0: the pin's input function is disabled.
 */
static inline _Bool gpio_is_input_en(gpio_pin_e pin)
{
    unsigned char bit = pin & 0xff;
    if (((pin >> 8) & 0xff) == GPIO_GROUP_ANA) {
        return BM_IS_SET(analog_read_reg8(areg_gpio_pana_setting), bit);
    } else {
        return BM_IS_SET(reg_gpio_ie(pin), bit);
    }
}

/**
 * @brief       This function is used to enable the GPIO pin of mspi.
 * @param[in]   none.
 * @return      none.
 * @note        This interface is for internal use only.
 */
static _always_inline void gpio_set_mspi_pin_ie_en(void)
{
    reg_gpio_ph_ie = 0xff;
    reg_gpio_pi_ie = 0x3f;
}

/**
 * @brief       This function is used to disable the GPIO pin of mspi.
 * @param[in]   none.
 * @return      none.
 * @note        This interface is for internal use only.
 */
static _always_inline void gpio_set_mspi_pin_ie_dis(void)
{
    reg_gpio_ph_ie = 0x00;
    reg_gpio_pi_ie = 0x00;
}

/**
 * @brief      This function serves to enable gpio irq0~7 function.
 * @param[in]  pin  - the pin needs to enable its IRQ.
 * @param[in]  irq  - there are 8 types of irq to choose.(irq0/irq1/irq2/irq3/irq4/irq5/irq6/irq7)
 * @return     none.
 */
static inline void gpio_irq_en(gpio_pin_e pin, gpio_irq_num_e irq)
{
    BM_SET(reg_gpio_irq_en(pin, irq), pin & 0xff);
}

/**
 * @brief      This function serves to disable gpio irq0 function.
 * @param[in]  pin  - the pin needs to disable its IRQ.
 * @param[in]  irq  - there are 8 types of irq to choose.(irq0/irq1/irq2/irq3/irq4/irq5/irq6/irq7)
 * @return     none.
 */
static inline void gpio_irq_dis(gpio_pin_e pin, gpio_irq_num_e irq)
{
    BM_CLR(reg_gpio_irq_en(pin, irq), pin & 0xff);
}

/**
 * @brief      This function serves to enable gpio irq mask function.
 * @param[in]  mask  - to select interrupt type.
 * @return     none.
 */
static inline void gpio_set_irq_mask(gpio_irq_e mask)
{
    BM_SET(reg_gpio_irq_src_mask, mask);
}

/**
 * @brief      This function serves to clr gpio irq status.
 * @param[in]  status  - the irq need to clear.
 * @return     none.
 */
static inline void gpio_clr_irq_status(gpio_irq_e status)
{
    reg_gpio_irq_clr = status;
}

/**
 * @brief      This function serves to disable gpio irq mask function.
 *             if disable gpio interrupt,choose disable gpio mask , use interface gpio_clr_irq_mask instead of gpio_irq_dis/gpio_gpio2risc0_irq_dis/gpio_gpio2risc1_irq_dis.
 * @return     none.
 */
static inline void gpio_clr_irq_mask(gpio_irq_e mask)
{
    BM_CLR(reg_gpio_irq_ctrl, mask);
}

/**
 * @brief     This function set a pin's IRQ , here you can choose from 8 interrupts for flexible configuration, each interrupt is independent and equal to each other.
 * @param[in] irq           - there are 8 types of irq to choose.(irq0/irq1/irq2/irq3/irq4/irq5/irq6/irq7)
 * @param[in] pin           - the pin needs to enable its IRQ.
 * @param[in] trigger_type  - gpio interrupt type.
 *                            0: rising edge.
 *                            1: falling edge.
 *                            2: high level.
 *                            3: low level.
 * @return    none.
 */
void gpio_set_irq(gpio_irq_num_e irq, gpio_pin_e pin, gpio_irq_trigger_type_e trigger_type);

/**
 * @brief      This function serves to set the gpio-mux function.
 * @param[in]  pin      - the pin needs to set.
 * @param[in]  function - the function need to set.
 * @return     none.
 */
void gpio_set_mux_function(gpio_func_pin_e pin, gpio_func_e function);

/**
 * @brief      This function set the input function of a pin.
 * @param[in]  pin - the pin needs to set the input function.
 * @return     none.
 */
void gpio_input_en(gpio_pin_e pin);

/**
 * @brief      This function disable the input function of a pin.
 * @param[in]  pin - the pin needs to set the input function.
 * @return     none.
 */
void gpio_input_dis(gpio_pin_e pin);

/**
 * @brief      This function set the input function of a pin.
 * @param[in]  pin - the pin needs to set the input function
 * @param[in]  value - enable or disable the pin's input function(1: enable,0: disable )
 * @return     none
 */
void gpio_set_input(gpio_pin_e pin, unsigned char value);

/**
 * @brief      This function servers to set the specified GPIO into High-impedance state and also enable the pull-down resistor.
 *             To prevent power leakage, you need to call gpio_shutdown(GPIO_ALL) (set all gpio to high resistance, except SWS and MSPI)
 *             as front as possible in the program, and then initialize the corresponding GPIO according to the actual using situation.
 * @param[in]  pin  - select the specified GPIO.Only support GPIO_GROUPA ~GPIO_GROUPI,GPIO_GPOUPANA and GPIO_ALL.
 * @return     none.
 */
void gpio_shutdown(gpio_pin_e pin);

/**
 * @brief     This function set a pin's pull-up/down resistor.
 * @param[in] pin - the pin needs to set its pull-up/down resistor.
 * @param[in] up_down_res - the type of the pull-up/down resistor.
 * @return    none.
 */
void gpio_set_up_down_res(gpio_pin_e pin, gpio_pull_type_e up_down_res);

/**
 * @brief     This function set pin's  pull-down register.
 * @param[in] pin - the pin needs to set its pull-down register.
 * @return    none.
 * @attention  This function sets the digital pull-down, it will not work after entering low power consumption.
 */
void gpio_set_digital_pulldown(gpio_pin_e pin);

/**
 * @brief     This function set pin's  pull-up register.
 * @param[in] pin - the pin needs to set its pull-up register.
 * @return    none.
 * @attention  This function sets the digital pull-up, it will not work after entering low power consumption.
 */
void gpio_set_digital_pullup(gpio_pin_e pin);

/**
 * @brief     This function disable pin's  pull-down register.
 * @param[in] pin - the pin needs to disable its pull-down register.
 * @return    none.
 */
void gpio_digital_pulldown_dis(gpio_pin_e pin);

/**
 * @brief     This function disable pin's  pull-up register.
 * @param[in] pin - the pin needs to disable its pull-up register.
 * @return    none.
 */
void gpio_digital_pullup_dis(gpio_pin_e pin);

/**
 * @brief     This function is used to enable the JTAG function of the dsp.
 * @param[in] dsp_jtag_pin - the pin selected as the DSP_JTAG.
 * @return    none.
 */
void dsp_jtag_enable(dsp_jtag_pin_st *dsp_jtag_pin);

/**
 * @brief     This function set probe clk output.
 * @param[in] pin
 * @param[in] sel_clk
 * @return    none.
 */
void gpio_set_probe_clk_function(gpio_func_pin_e pin, probe_clk_sel_e sel_clk);
/**
 * @brief      This function set the pin's driving strength at strong.
 * @param[in]  pin - the pin needs to set the driving strength.
 * @return     none.
 */
void gpio_ds_en(gpio_pin_e pin);


/**
 * @brief      This function set the pin's driving strength.
 * @param[in]  pin - the pin needs to set the driving strength at poor.
 * @return     none.
 */
void gpio_ds_dis(gpio_pin_e pin);
#endif
